using Microsoft.AspNetCore.Http;
using Microsoft.EntityFrameworkCore;
using Serilog;
using Universal.Application.Contracts.Common;
using Universal.Application.Contracts.Dto.Log;
using Universal.Application.Repositories;
using Universal.Domain.Entities.App;
using Universal.Domain.Repositories;
using System.IdentityModel.Tokens.Jwt;

namespace Universal.Application.Services;

public class LogService : ILogService
{
    private readonly IRepository<AppLog> _logRepository;
    private readonly IHttpContextAccessor _httpContextAccessor;

    public LogService(IRepository<AppLog> logRepository, IHttpContextAccessor httpContextAccessor)
    {
        _logRepository = logRepository;
        _httpContextAccessor = httpContextAccessor;
    }

    public async Task WriteLogAsync(string action)
    {
        var context = _httpContextAccessor.HttpContext;
        var ip = context?.Connection?.RemoteIpAddress?.ToString();
        var ua = context?.Request?.Headers["User-Agent"].ToString();

        // 检查Authorization header
        var authHeader = context?.Request?.Headers["Authorization"].ToString();

        // 尝试多种方式获取用户ID
        Guid userId = Guid.Empty;
        string? userIdStr = null;

        // 方法1: 从User Claims中获取sub
        userIdStr = context?.User?.FindFirst("sub")?.Value;

        // 方法2: 如果方法1失败，尝试手动解析JWT token
        if (string.IsNullOrEmpty(userIdStr) && !string.IsNullOrEmpty(authHeader) && authHeader.StartsWith("Bearer "))
        {
            var token = authHeader.Substring("Bearer ".Length);

            try
            {
                var handler = new JwtSecurityTokenHandler();
                var jsonToken = handler.ReadJwtToken(token);

                // 特别检查sub claim
                var subClaim = jsonToken.Claims.FirstOrDefault(c => c.Type == "sub");
                if (subClaim != null)
                {
                    userIdStr = subClaim.Value;
                }
                else
                {
                    // 没有找到sub claim，继续尝试其他方法
                }
            }
            catch (Exception)
            {
                // JWT Token解析失败，继续尝试其他方法
            }
        }

        // 尝试解析用户ID
        if (!string.IsNullOrEmpty(userIdStr) && Guid.TryParse(userIdStr, out var parsedUserId))
        {
            userId = parsedUserId;
        }

        var log = new AppLog
        {
            Id = Guid.NewGuid(),
            UserId = userId, // 如果解析失败，使用空GUID
            Action = action,
            IpAddress = ip,
            UserAgent = ua,
            CreatedAt = DateTime.UtcNow,
            UpdatedAt = DateTime.UtcNow,
            IsActive = true
        };

        try
        {
            await _logRepository.AddAsync(log);
        }
        catch (Exception ex)
        {
            Log.Error(ex, "写入日志到数据库失败: {Action}", action);
        }
    }

    /// <summary>
    /// 基本分页获取日志列表
    /// </summary>
    public async Task<ApiResponse<PagedResult<LogViewDto>>> GetLogsPagedAsync(int pageIndex, int pageSize)
    {
        // 最简单的分页逻辑
        var query = _logRepository.Query();
        var totalCount = await query.CountAsync();

        var logs = await query
            .OrderByDescending(l => l.CreatedAt)
            .Skip((pageIndex - 1) * pageSize)
            .Take(pageSize)
            .ToListAsync();

        var logDtos = logs.Select(log => new LogViewDto
        {
            CreatedAt = log.CreatedAt,
            UserId = log.UserId,
            Action = log.Action,
            IpAddress = log.IpAddress,
            UserAgent = log.UserAgent
        }).ToList();

        var pagedResult = new PagedResult<LogViewDto>
        {
            TotalCount = totalCount,
            TotalPages = (int)Math.Ceiling(totalCount / (double)pageSize),
            PageIndex = pageIndex,
            PageSize = pageSize,
            Items = logDtos
        };

        return ApiResponse<PagedResult<LogViewDto>>.Success(pagedResult);
    }

    /// <summary>
    /// 查询日志列表（支持时间范围过滤）
    /// </summary>
    public async Task<ApiResponse<PagedResult<LogViewDto>>> QueryLogsAsync(LogQueryDto query)
    {
        if (query == null)
        {
            return ApiResponse<PagedResult<LogViewDto>>.Failure(4001, "查询参数不能为空");
        }

        // 最简单的查询逻辑
        var baseQuery = _logRepository.Query();

        // 应用时间范围过滤，确保使用UTC时间
        if (query.StartTime.HasValue)
        {
            var startTime = query.StartTime.Value;
            if (startTime.Kind == DateTimeKind.Unspecified)
            {
                startTime = DateTime.SpecifyKind(startTime, DateTimeKind.Utc);
            }
            else if (startTime.Kind == DateTimeKind.Local)
            {
                startTime = startTime.ToUniversalTime();
            }
            baseQuery = baseQuery.Where(l => l.CreatedAt >= startTime);
        }

        if (query.EndTime.HasValue)
        {
            var endTime = query.EndTime.Value;
            if (endTime.Kind == DateTimeKind.Unspecified)
            {
                endTime = DateTime.SpecifyKind(endTime, DateTimeKind.Utc);
            }
            else if (endTime.Kind == DateTimeKind.Local)
            {
                endTime = endTime.ToUniversalTime();
            }
            baseQuery = baseQuery.Where(l => l.CreatedAt <= endTime);
        }

        var totalCount = await baseQuery.CountAsync();

        var logs = await baseQuery
            .OrderByDescending(l => l.CreatedAt)
            .Skip((query.PageIndex - 1) * query.PageSize)
            .Take(query.PageSize)
            .ToListAsync();

        var logDtos = logs.Select(log => new LogViewDto
        {
            CreatedAt = log.CreatedAt,
            UserId = log.UserId,
            Action = log.Action,
            IpAddress = log.IpAddress,
            UserAgent = log.UserAgent
        }).ToList();

        var pagedResult = new PagedResult<LogViewDto>
        {
            Items = logDtos,
            TotalCount = totalCount,
            TotalPages = (int)Math.Ceiling(totalCount / (double)query.PageSize),
            PageIndex = query.PageIndex,
            PageSize = query.PageSize
        };

        return ApiResponse<PagedResult<LogViewDto>>.Success(pagedResult);
    }
}